#include "CTcpAcceptor.h"
#include "CTcpAcceptorImpl.h"
#include "CNetService.h"
#include "CTcpSocket.h"

namespace TB
{
	CTcpAcceptor::CTcpAcceptor()
	{
        m_poImpl = std::make_shared<CTcpAcceptorImpl>();
	}

	CTcpAcceptor::~CTcpAcceptor()
	{
		Close();
	}

    std::weak_ptr<CNetService>& CTcpAcceptor::GetNetService()
    {
        return m_poImpl->GetNetService();
    }

    const std::weak_ptr<CNetService>& CTcpAcceptor::GetNetService() const
    {
        return m_poImpl->GetNetService();
    }

	bool CTcpAcceptor::Init(const std::weak_ptr<CNetService>& poNetService)
	{
        return m_poImpl->Init(poNetService, m_poImpl);
	}

    bool CTcpAcceptor::SetReuseAddr(bool bReuse)
    {
        return m_poImpl->SetReuseAddr(bReuse);
    }

	ENetErrorCode CTcpAcceptor::Listen(UINT32 dwIP, UINT16 wPort, UINT32 dwBacklog) //主机字节序
	{
        return m_poImpl->Listen(dwIP, wPort, dwBacklog);
	}

	STask<std::pair<ENetErrorCode, std::shared_ptr<CTcpSocket>>> CTcpAcceptor::Accept()
	{
        auto sTaskProcessor = CTaskHelper::CreatePendingTask<std::pair<ENetErrorCode, std::shared_ptr<CTcpSocket>>>();
        auto poNetService = m_poImpl->GetNetService().lock();
        if (!poNetService)
            return CTaskHelper::Resolve<std::pair<ENetErrorCode, std::shared_ptr<CTcpSocket>>>({ ENetErrorCode::OperationAborted, nullptr });
        auto poCoroutine = poNetService->GetCoroutine().lock();
        if (!poCoroutine)
            return CTaskHelper::Resolve<std::pair<ENetErrorCode, std::shared_ptr<CTcpSocket>>>({ ENetErrorCode::OperationAborted, nullptr });
        if (CCoroutine::GetCurrent() == poCoroutine)
        {
            m_poImpl->Accept(sTaskProcessor);
        }
        else
        {
            std::weak_ptr<CTcpAcceptorImpl> poWeakPtr = m_poImpl;
            poCoroutine->Post([sTaskProcessor, poWeakPtr]() mutable
            {
                auto poImpl = poWeakPtr.lock();
                if (poImpl == nullptr)
                {
                    sTaskProcessor.Resolve({ ENetErrorCode::OperationAborted, nullptr });
                    return;
                }
                poImpl->Accept(sTaskProcessor);
            });
        }
        return sTaskProcessor.GetTask();
	}

    bool CTcpAcceptor::GetLocalIpPort(std::pair<UINT32, UINT16>& roIpPort) const //主机字节序
	{
        return m_poImpl->GetLocalIpPort(roIpPort);
	}

	bool CTcpAcceptor::IsClosed() const
	{
        return m_poImpl->IsClosed();
	}

	void CTcpAcceptor::Close()
	{
        if (IsClosed())
            return;
        auto poNetService = m_poImpl->GetNetService().lock();
        auto poCoroutine = !poNetService ? nullptr : poNetService->GetCoroutine().lock();
        if (poCoroutine == nullptr || CCoroutine::GetCurrent() == poCoroutine)
        {
            m_poImpl->Close();
        }
        else
        {
            std::shared_ptr<CTcpAcceptorImpl> poImpl = m_poImpl;
            poCoroutine->Post([poImpl]() mutable
            {
                poImpl->Close();
            });
        }
	}
}